/**
 * Copyright (2023, ) Institute of Software, Chinese Academy of Sciences
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.ac.iscas.protocols;

import java.util.Base64;

import org.apache.hc.client5.http.classic.methods.HttpDelete;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpPut;
import org.apache.hc.client5.http.classic.methods.HttpUriRequestBase;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.io.entity.StringEntity;

import cn.ac.iscas.sources.HttpSource;
import cn.ac.iscas.sources.http.HttpAPiKeySource;
import cn.ac.iscas.sources.http.HttpCookieSource;
import cn.ac.iscas.sources.http.HttpPublicSource;
import cn.ac.iscas.sources.http.HttpTokenSource;
import cn.ac.iscas.sources.http.HttpUserSource;

/**
 * 
 * It is used for creating various HttpRequest
 * 
 * @author wuheng@iscas.ac.cn
 * @since 1.0.5
 **/
public class HttpProtocol {

	/**********************************************************
	 * 
	 * Commons
	 * 
	 **********************************************************/

	/**
	 * 
	 */
	private HttpProtocol() {
		super();
	}

	/**
	 * @param config config
	 * @param body  body
	 * @return request
	 */
	private static HttpUriRequestBase createRequest(HttpSource config, String body) {
		HttpUriRequestBase request = config.getRequest();
		setBodyIfNeeds(request, body);
		setHeaders(config, request);
		
		return request;
	}

	/**
	 * @param config   config
	 * @param request  request
	 */
	public static void setHeaders(HttpSource config, HttpUriRequestBase request) {
		if (config instanceof HttpCookieSource) {
			setCookie(request, ((HttpCookieSource) config).getCookie());
		} else if (config instanceof HttpTokenSource) {
			setToken(request, ((HttpTokenSource) config).getToken());
		} else if (config instanceof HttpUserSource) {
			setUser(request, ((HttpUserSource) config).getUsername(),
					((HttpUserSource) config).getPassword());
		} else if (config instanceof HttpAPiKeySource) {
			setApiKey(request, ((HttpAPiKeySource) config).getApikey());
		} else if (config instanceof HttpPublicSource) {
			//;
		} else {
			throw new UnsupportedOperationException("unsupport operations");
		}
	}

	/**
	 * @param request
	 * @param body
	 */
	public static void setBodyIfNeeds( HttpUriRequestBase request, String body) {
		try {
			request.setEntity(new StringEntity(
					body == null ? "" : body, ContentType.APPLICATION_JSON));
		} catch (Exception ex) {
			// ignore here
		}
	}
	
	/**
	 * @param request request
	 * @param token   token
	 */
	private static void setToken(HttpUriRequestBase request, String token) {
		request.addHeader("Authorization", "Bearer " + token);
		request.addHeader("Connection", "keep-alive");
	}
	
	
	/**
	 * @param request
	 * @param username
	 * @param password
	 */
	private static void setUser(HttpUriRequestBase request, String username, String password) {
		request.addHeader("Authorization", "Basic " 
							+ Base64.getEncoder().encodeToString(
								(username + ":" + password).getBytes()));
		request.addHeader("Connection", "keep-alive");
	}
	
	/**
	 * @param request
	 * @param apiKey
	 */
	private static void setApiKey(HttpUriRequestBase request, String apiKey) {
		
		request.addHeader("Connection", "keep-alive");
		request.addHeader("X-Api-Key", apiKey);
	}
	
	/**
	 * @param request
	 * @param cookie
	 */
	private static void setCookie(HttpUriRequestBase request, String cookie) {
		
		request.addHeader("Connection", "keep-alive");
		request.addHeader("Cookie", cookie);
	}
	

	/**********************************************************
	 * 
	 * Core
	 * 
	 **********************************************************/
	/**
	 * @param config config
	 * @param body  body
	 * @return request or null
	 */
	public static HttpPost post(HttpSource config, String body) {
		return (HttpPost) createRequest(config, body);
	}

	/**
	 * @param config config
	 * @param body  body
	 * @return request or null
	 */
	public static HttpPut put(HttpSource config, String body) {
		return (HttpPut) createRequest(config, body);
	}

	/**
	 * @param config config
	 * @return request or null
	 */
	public static HttpDelete delete(HttpSource config) {
		return (HttpDelete) createRequest(config, null);
	}

	/**
	 * @param config config
	 * @return request or null
	 */
	public static HttpGet get(HttpSource config)  {
		return (HttpGet) createRequest(config, null);
	}

}
